package dao;

import dao.inte.AbstractEntityRepositoryInterface;
import domain.AbstractEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

@Transactional(propagation = Propagation.REQUIRED)
@Service
public abstract class AbstractEntityRepository<T extends AbstractEntity> implements AbstractEntityRepositoryInterface<T> {
    private Class<T> domainClass;
    @PersistenceContext
    public EntityManager entityManager;

    protected AbstractEntityRepository() {
    }

    public AbstractEntityRepository(Class<T> domainClass) {
        this.domainClass = domainClass;
    }

    @Transactional
    public T findById(Long id) {
        return (T) entityManager.find(getEntityClass(), id);
    }

    public List<T> findAll() {
        return entityManager.createQuery("from " + getEntityClass().getCanonicalName()).getResultList();
    }

    public T findLast() {
        Long id = Long.valueOf(entityManager.createQuery("SELECT max(id) from " + getEntityClass().getCanonicalName()).getSingleResult().toString());
        return findById(id);
    }

    @Transactional(readOnly = false)
    public T save(T object) throws Exception {
        if (object.getId() == null) {
            entityManager.persist(object);

        } else {
            entityManager.merge(object);
        }
        return (T) object;
    }

    public int count() {
        return Integer.valueOf(entityManager.createQuery("SELECT COUNT(*) FROM " + getEntityClass().getCanonicalName()).getSingleResult().toString());

    }

    @Transactional
    public void delete(T object) {
        entityManager.remove(object);
    }

    protected abstract Class<T> getEntityClass();
}
